package com.mytinyRPC.framework.loadBalance.Impl;



import com.mytinyRPC.Factory.SingletonFactory;
import com.mytinyRPC.framework.URL;
import com.mytinyRPC.framework.loadBalance.LoadBalance;
import com.mytinyRPC.register.ServiceDiscovery;
import com.mytinyRPC.register.zookeeperRegister.ZkServiceDiscovery;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/***
 * @Author HP
 * @Description //TODO 平滑加权随机算法
 **/
public class SmoothWeightedRandom implements LoadBalance {
    //集群权值之和
    private static volatile Integer smoothtotal=0;
    //保存当前权重用于平滑加权随机算法
    private static Map<String, ConcurrentHashMap<URL,Integer>> curWeights=new ConcurrentHashMap<>();

    private static final ServiceDiscovery serviceDiscovery;
    static {
        serviceDiscovery = SingletonFactory.getInstance(ZkServiceDiscovery.class);
    }

    /***
     * @Author HP
     * @Description //平滑加权随机算法
     * @Name SmoothWeightedRandom
     * @Param [list]
     * @return framework.URL
     **/
    private URL SmoothWeightedRandom(List<URL> list,String interfaceName){
        if (list.size()<=0){
            return null;
        }
        ConcurrentHashMap<URL,Integer> weights=curWeights.get(interfaceName);
        //计算权值之和
        smoothtotal=0;
        for (int i = 0; i <list.size() ; i++) {
            smoothtotal+=list.get(i).getWeight();
        }
        //取当前权值最大的URL
        Collections.sort(list,(URL a, URL b)->(weights.get(b)-weights.get(a)));
        //选中的URL的当前权值减去smoothtotal
        URL result=list.get(0);
        int afterweight=weights.get(result)-smoothtotal;
        weights.replace(list.get(0),afterweight);
        //URL当前权值加上固定权值
        for (int i = 0; i <list.size() ; i++) {
            weights.replace(list.get(i),weights.get(list.get(i))+list.get(i).getWeight());
        }
        System.out.println("选择负载服务器:"+ result.toString());
        return result;
    }

    @Override
    public URL loadBalance(String interfaceName) {
        if (!curWeights.containsKey(interfaceName)){
            curWeights.put(interfaceName,new ConcurrentHashMap<URL,Integer>());
        }
        //List<URL> urlList= RemoteMapRegister.getURL(interfaceName);
        List<URL> urlList= serviceDiscovery.getURL(interfaceName);
        for (URL url:urlList){
            if (!curWeights.get(interfaceName).containsKey(url)){
                curWeights.get(interfaceName).put(url,0);
            }
        }
        //return random(urlList);
        return SmoothWeightedRandom(urlList,interfaceName);
    }
}
